<template>
  <div class="content" :class="isMove?'user-select-none':''" 
  v-loading="loading" element-loading-text="模板加载中">
    <!-- 顶部 -->
    <div class="content-top flex-row-between" @click="changeInfo">
      <div class="content-top-left flex-row-start">
        <span style="font-size: 14px;color: gray;">表内设置</span>
        <el-select
          v-model="form.configurationValue"
          placeholder="请选择画布宽度"
          @change="handleConfigurationChange"
          class="width100"
        >
          <el-option
            v-for="item in configuration"
            :key="item"
            :label="item"
            :value="item"
          >
          </el-option>
        </el-select>
        <el-select
          v-model="form.fontFamilyValue"
          placeholder="请选择输入框字体系列"
          class="width100"
          @change="handleFontFamilyChange"
          :disabled="listStyle===null"
        >
          <el-option
            v-for="item in fontFamily"
            :key="item.id"
            :label="item.font"
            :value="item.id"
          >
          </el-option>
        </el-select>
        <el-input
          placeholder="请输入"
          v-model="form.fontSize"
          type="number"
          :min="minValue"
          class="width170"
          @input="handleFontSizeChange"
          :disabled="listStyle===null"
        >
          <template slot="prepend">
            <el-select
              v-model="form.fontAttributeValue"
              placeholder="请选择输入框字体系列"
              class="selectFontSize"
              @change="handleFontAttributeValueChange"
              :disabled="listStyle===null"
            >
              <el-option
                v-for="item in fontAttribute"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              >
              </el-option>
            </el-select>
          </template>
        </el-input>
        <div :style="{ cursor: listStyle === null ? 'not-allowed' : '' }">
          <div class="iconCard flex-row-start"
            :style="{ pointerEvents: listStyle === null ? 'none' : '', opacity: listStyle === null ? 0.5 : 1 }">
            <!-- 字体加粗 -->
            <svg-icon-card IconClass="FontWidth" mouseIconClass="FontWidth" prompt="字体加粗"
              @iconClick="setFontStyle" :style="{background: (listStyle || {}).fontWeight == 'bolder' ? '#03A98E' : ''}"></svg-icon-card>
            <!-- 字体斜体 -->
            <svg-icon-card IconClass="italic" mouseIconClass="italic" prompt="字体斜体"
              @iconClick="setFontStyle" :style="{background: (listStyle || {}).fontStyle == 'italic' ? '#03A98E' : ''}"></svg-icon-card>
            <!-- 字体添加下划线 -->
            <svg-icon-card IconClass="line" mouseIconClass="line" prompt="字体下划线"
              @iconClick="setFontStyle" :style="{background: (listStyle || {}).textDecoration == 'underline' ? '#03A98E' : ''}"></svg-icon-card>
            <!-- 字体左对齐 -->
            <svg-icon-card IconClass="justifyLeft" mouseIconClass="justifyLeft" prompt="字体左对齐"
              @iconClick="setFontStyle" :style="{background: (listStyle || {}).textAlign == 'left' ? '#03A98E' : ''}"></svg-icon-card>
            <!-- 字体居中对齐 -->
            <svg-icon-card IconClass="justifyCenter" mouseIconClass="justifyCenter" prompt="字体居中对齐"
              @iconClick="setFontStyle" :style="{background: (listStyle || {}).textAlign == 'center' ? '#03A98E' : ''}"></svg-icon-card>
            <!-- 字体右对齐 -->
            <svg-icon-card IconClass="justifyRight" mouseIconClass="justifyRight" prompt="字体右对齐"
              @iconClick="setFontStyle" :style="{background: (listStyle || {}).textAlign == 'right' ? '#03A98E' : ''}"></svg-icon-card>
          </div>
        </div>

        <!-- <div class="iconCard flex-row-start"> -->
          <!-- 左对齐 -->
          <!-- <svg-icon-card
            IconClass="justifyRight"
            mouseIconClass="FontWidth"
            prompt="左对齐"
          ></svg-icon-card> -->
        <!-- </div> -->
        <!-- <div :style="{ cursor: listStyle === null ? 'not-allowed' : '' }">
          <div class="iconCard flex-row-start" :style="{ pointerEvents: listStyle === null ? 'none' : '', opacity: listStyle === null ? 0.5 : 1 }">
            移动到表头区
            <svg-icon-card IconClass="meterHeader" mouseIconClass="meterHeader" prompt="移动到表头区" @iconClick="moveTable"></svg-icon-card>
            移动到表尾区
            <svg-icon-card IconClass="meterend" mouseIconClass="meterend" prompt="移动到表尾区" @iconClick="moveTable"></svg-icon-card>
          </div>
        </div> -->
      </div>
      <div>
        <el-button @click="preview('preview')">打印预览</el-button>
        <el-button @click="close">关闭</el-button>
        <el-button type="primary" @click="preview('save')">保存</el-button>
      </div>
    </div>
    <!-- 文字 条码 线段提示弹框 -->
    <bllet-box :info.sync="textInfo" @addList="addList"></bllet-box>
    <bllet-box :info.sync="codeInfo"></bllet-box>
    <bllet-box :info.sync="lineInfo" @addLine="addLine"></bllet-box>
    <!-- 左部 -->
    <div class="content-left flex-column-start">
      <!-- 撤回 -->
      <!-- <div class="content-left-box flex-column-center">
        <svg-icon-card
          IconClass="withdraw"
          mouseIconClass="withdraw"
        ></svg-icon-card>
        <span>撤回</span>
      </div> -->

      <!-- 重做 -->
      <div class="content-left-box flex-column-center" @click="reload()">
        <svg-icon-card IconClass="redo" mouseIconClass="redo"></svg-icon-card>
        <span>重做</span>
      </div>

      <!-- 文字 -->
      <div class="content-left-box flex-column-center" id="text" @click="showBlletBox('text')">
        <svg-icon-card IconClass="text" mouseIconClass="text"></svg-icon-card>
        <span>文字</span>
      </div>

      <!-- 图片 -->
      <!-- <div class="content-left-box flex-column-center">
        <svg-icon-card IconClass="image" mouseIconClass="image"></svg-icon-card>
        <span>图片</span>
      </div> -->

      <!-- 条码 -->
      <!-- <div class="content-left-box flex-column-center" id="code" @click="showBlletBox('code')">
        <svg-icon-card IconClass="code" mouseIconClass="code"></svg-icon-card>
        <span>条码</span>
      </div> -->

      <!-- 线段 -->
      <div class="content-left-box flex-column-center" id="line2" @click="showBlletBox('line2')">
        <svg-icon-card IconClass="line2" mouseIconClass="line2"></svg-icon-card>
        <span>线段</span>
      </div>
    </div>

    <!-- 右部 -->
    <div class="content-right">
      <right-card @operate="operate" @changePageData="changePageData" @getList="getList" ref="RightCard"></right-card>
    </div>

    <!-- 中部 -->
    <div class="content-meddle" @click="changeInfo">
      <div id="pageBox" @click="clearStyle" @mousewheel="mouseWheel" :style="pageData">
        <div class="pageBox-line">
          <div class="title">{{pageData['--width']}}</div>
        </div>
        <div class="pageBox-vertical">
          <div class="title">{{pageData['--height']}}</div>
        </div>
        <template v-for="(item, index) in list">
          <div 
            :key="item.id"
            class="container"
            :style="[select === index ? selectStyle : noselect(item),item.containerStyle,item.name==='二维码' ? qrcodeStyle : {}]"
            :id="'select' + item.id"
            @click.stop="clickBox(item, index)" 
            v-show="item.type != 'table' || item.columns.length || item.countList.length"
            @mouseenter="downBox($event,item,index)"
          >
            <!-- 自定义文字 -->
            <textarea v-model="item.name" :style="item.style" v-if="item.type == 'input'"></textarea>
            <!-- 表格 -->
            <div class="table-wrapper" :style="item.style" v-else-if="item.type=='table'">
              <!-- 商品信息 -->
              <table id="table">
                <thead>
                  <th v-for="(items,index) in item.columns" :key="items.id" :width="items.width"
                  draggable @dragstart="dragstart(index)" @dragover="dragover"
                  @drop="drop($event,index,item.columns)" @dragleave="dragleave">
                    <span>{{ items.name }}</span>
                    <p class="resizable" @mousedown.stop.prevent="startColumn(item.columns, index,'tbody')"></p>
                  </th>
                </thead>
                <tbody>
                  <tr v-for="items in ruleList" :key="items.id">
                    <td v-for="itm in item.columns" :key="itm.id">
                      <span>{{ items[itm.name] }}</span>
                    </td>
                  </tr>
                </tbody>
              </table>
              <!-- 合计信息 -->
              <table id="countTable">
                <thead>
                  <td v-for="(items,index) in item.countList" :key="items.id" :width="items.width" :style="{'border-top-width': item.columns.length?0:1}"
                  draggable @dragstart="dragstart(index)" @dragover="dragover"
                  @drop="drop($event,index,item.countList)" @dragleave="dragleave">
                    <span>{{ items.name }}</span>
                    <p class="resizable" @mousedown.stop.prevent="startColumn(item.countList, index,'tfood')"></p>
                  </td>
                </thead>
              </table>
            </div>
            <!-- 签字信息 -->
            <div :style="item.style" v-else-if="item.type=='sign'">{{ item.name }}</div>
            <!-- 订单信息 -->
            <div :style="item.style" :class="item.name === '二维码' ? 'qrcode' : ''" v-else>
              {{ item.name !== '二维码' ? item.name : "" }}
            </div>
            <div class="point top" v-if="select === index && item.style.height"></div>
            <div class="point left" v-if="select === index && item.style.width"></div>
            <div class="point right" v-if="select === index && item.style.width"></div>
            <div class="point bottom" v-if="select === index  && item.style.height"></div>
            <div class="point top-left" v-if="select === index && item.style.height && item.style.width"></div>
            <div class="point top-right" v-if="select === index && item.style.height  && item.style.width"></div>
            <div class="point bottom-left" v-if="select === index && item.style.height  && item.style.width"></div>
            <div class="point bottom-right" v-if="select === index && item.style.height  && item.style.width"></div>
          </div>
        </template>
        <div class="Xline" style="width: 0" ref="lineTopX"></div>
        <div class="Xline" style="width: 0" ref="lineMeddleX"></div>
        <div class="Xline" style="width: 0" ref="lineBottomX"></div>

        <div class="Yline" style="height: 0" ref="lineTopY"></div>
        <div class="Yline" style="height: 0" ref="lineMeddleY"></div>
        <div class="Yline" style="height: 0" ref="lineBottomY"></div>
      </div>
    </div>
    <preview ref="preview" :width="pageData['--width']" :height="pageData['--height']" @save="save"></preview>
  </div>
</template>

<script>
import RightCard from "./components/RightCard.vue";
import SvgIconCard from "./components/SvgIconCard.vue";
import BlletBox from "./components/BlletBox.vue";
import Preview from "./components/Preview.vue";
import { configuration, fontFamily, fontAttribute , ruleList } from "./configuration.js";
import { compareTopHeight, replaceFun } from "@/utils/print";
import { packApi } from "@/utils/public";
import { addNewTemplate, save_order_print } from "@/api/global/globalNewPrint";
export default {
  components: {
    RightCard,
    SvgIconCard,
    BlletBox,
    Preview
  },
  inject:["reload", "broadcast"],
  data() {
    return {
      // 画布宽度数组
      configuration,
      // 字体系列数组
      fontFamily,
      // 设置初始字体大小、字体间距、字体行高
      fontAttribute,
      // 表格的数据
      ruleList,
      form: {
        // 画布初始宽度
        configurationValue: "100%",
        // 字体初始系列
        fontFamilyValue: 1,
        // 字体初始字体大小、字体间距、字体行高
        fontAttributeValue: 1,
        // 字体大小
        fontSize: null,
        // 纸张方向
        direction: 1,
      },

      list: [],
      //初始样式
      initStyle: {
        width: '100%',
        height: '100%',
        fontFamily: '黑体',
        fontStyle: 'normal',
        fontSize: '14px',
        fontWeight: 'normal',
        textAlign: 'left',
        textDecoration: 'none',
        lineHeight: '20px',
        letterSpacing: '1px'
      },
      containerInitStyle: {
        width: '105px',
        height: '30px',
        lineHeight: '20px'
      },
      // 需要修改样式对象
      listStyle: null,
      containerStyle: null,
      pageData: {
        "--width": "210mm",
        "--height": "297mm",
      },
      // 页面对象
      pageObj: null,
      // 缩放元素
      zoomBox: null,
      // 鼠标按下时的坐标，并在修改尺寸时保存上一个鼠标的位置
      clientX: 0,
      clientY: 0,
      // div可修改的最小宽高
      minW: 20,
      minH: 20,
      // 鼠标按下时的位置，使用n、s、w、e表示
      direc: "",
      select: "",
      selectStyle: {
        border: "1px dashed #19be6b",
        cursor: "pointer",
      },
      // 拖拽
      moveType: "",
      disX: 0,
      disY: 0,
      ShowLine: false,
      // 横向辅助线三个点位
      XtransverseList: ["lineTopX", "lineMeddleX", "lineBottomX"],
      // 竖向辅助线三个点位
      YtransverseList: ["lineTopY", "lineMeddleY", "lineBottomY"],
      // 对比元素
      contrastBoxs: null,
      // 辅助线展示的位置：1代表三条辅助线，2代表上边框辅助线，3代表中部辅助线，4代表下边框辅助线
      guideLine: null,
      //文字 条码 线段提示弹框
      textInfo: { show: false, text: "文字" },
      codeInfo: { show: false, text: "条码" },
      lineInfo: { show: false, text: "线段" },
      dragIndex: null, // 表格列拖拽的下标
      startX: null, // 鼠标按下时坐标，修改表格列宽的鼠标位置
      dragging: false, // 列是否在拖动
      columnIndex: null, // 修改列宽的下表
      columnList: null,  // 修改表格的数据
      columnType: '', // 修改列宽时候的表格类型
      isMove: false, // 是否在移动
      loading: true, // 加载loading
      isSave: false, // 是否在保存
      qrcodeStyle: {
        width: "80px",
        height: "80px",
      },
      tem_id: this.$route.query.tem_id, // 模版id
    };
  },
  computed: {
    // 未选择的元素保持原有的z-indx层级
    noselect: function () {
      return function (item) {
        this.$nextTick(() => {
          // dom元素更新后执行，因此这里能正确打印更改之后的值
          let obj = document.getElementById("select" + item.id);
          let sty = {
            zIndex: obj.style.zIndex,
          };
          return sty;
        });
        return "";
      };
    },
    prompt() {
      let newFontAttribute = this._.cloneDeep(fontAttribute);
      let list = newFontAttribute.filter(
        (item) => item.id == this.form.fontAttributeValue
      );
      return list[0].label || "字号";
    },
    // 计算输入框的最小值
    minValue() {
      const valueMap = { 1: 12, 2: 0 };
      return valueMap[this.form.fontAttributeValue] || 1; // 默认返回 1
    },
  },
  mounted() {
    this.pageObj = document.getElementById("pageBox");
  },
  watch: {
    listStyle: {
      // 选中元素进行fontSize回填
      handler(val) {
        if (val !== null) {
          const type = this.getFontAttributeType();
          this.form.fontSize = val[type] ? parseInt(val[type]) : this.form.fontAttributeValue != 1 ? 16 : 1;
          let fontInfo = fontFamily.find(item=> item.font == val.fontFamily);
          if(fontInfo) this.form.fontFamilyValue = fontInfo.id;
        } else {
          this.form.fontSize = null // 未选中是将fontSize清空
        }
      },
      deep: true
    },
  },
  methods: {
    // 编辑回显页面
    getList(data){
      data && (this.list = data);
      this.loading = false;
    },
    // 保存
    save(){
      if(this.isSave) return; // 防止重复提交
      this.isSave = true;
      let rightCard = this.$refs.RightCard;
      // 计算表格位置
      this.calculateTablePositions();
      // 用户信息
      let memberIds = this.getMemberIds();
      let printSetting = {
        fontset: rightCard.pageFontSet,
        page: rightCard.page,
        printSetting: rightCard.printSetting
      };
      let data = packApi({
        tem_id: this.$route.query.tem_id,
        data_source_list: JSON.stringify(rightCard.list),
        main_settings: JSON.stringify(this.list),
        tem_name: rightCard.tem_name,
        remark: rightCard.remark,
        member_ids: memberIds.join(","),
        print_settings: JSON.stringify(printSetting),
        goods_discount: rightCard.goods_discount,
        is_new: 1,
      })
      const apiCall = this.$route.query.id ? save_order_print : addNewTemplate;
      if (this.$route.query.id) data.id = this.$route.query.id;
      apiCall(data).then(res=> {
        if (res.errcode === 0) {
          this.$message.success(this.$route.query.id ? "修改模板成功" : "新增模板成功");
          this.broadcast.postMessage({ path: "/delivery/index", msg: "操作成功" }); // 通知页面请求接口
          setTimeout(() => {
            window.close();
            this.isSave = false;
          }, 1000);
        } else {
          this.isSave = false;
          this.$message.error(res.errmsg);
        }
      }).catch(() => {
        this.$message.error("操作失败");
        this.isSave = false;
      });
    },
    // 关闭窗口
    close(){
      window.close()
    },
    // 预览
    preview(save){
      const rightCard = this.$refs.RightCard;
      if(save === 'save') {
        if(this.$route.query.change_user == 1) {
          let member_ids = this.getMemberIds();
          if(!member_ids.length) return this.$message.error("请选择用户");
        }
        const validateDecimal = value => {
          const num = parseFloat(value);
          return !isNaN(num) && num > 0 && num <= 1 && Number(num.toFixed(3)) === num;
        };
        if(rightCard.goods_discount && !validateDecimal(rightCard.goods_discount) && this.tem_id == 9) {
          this.$message.error("全商品折扣请输入小于等于1且大于等于0的三位小数");
          return;
        }
      }
      // 计算表格位置
      this.calculateTablePositions();
      let printSetting = { 
        fontset: rightCard.pageFontSet,
        page: rightCard.page,
        printSetting: rightCard.printSetting
      };
      let data = {
        main_settings: JSON.stringify(this.list),
        print_settings: JSON.stringify(printSetting),
        type: 'order',
        tem_id: this.$route.query.tem_id,
        save
      }
      this.$refs.preview.open(data);
    },
    // 提取公共部分的函数，用于获取并计算表格的位置
    calculateTablePositions() {
      const table = document.getElementById('table');
      const countTable = document.getElementById('countTable');
      const tableTop = parseInt(this.list.find(item => item.type === 'table').containerStyle.top);
      this.list.forEach(item => {
        if(item.type === 'sign') {
          item.top = parseInt(item.containerStyle.top) - countTable.offsetHeight - tableTop - table.offsetHeight;
        }
      });
    },
    // 提取并返回用户标签ID列表
    getMemberIds() {
      const rightCard = this.$refs.RightCard;
      const newUserTags = rightCard.user_tags.concat(rightCard.more_user_tags);
      return newUserTags.map(tag => tag.id);
    },
    // 创建鼠标抬起事件
    createMouseUpEvent() {
      return new MouseEvent('mouseup', {
        bubbles: true,
        cancelable: true,
        view: window
      });
    },
    // 处理目标元素的类名，避免重复代码
    updateTargetClass(e, className) {
      if (e.target.localName === 'th') { // 选中的是td给自己加类名
        e.target.classList.add(className);
      } else if (e.target.localName === 'span' || e.target.localName === 'p') { // 选中的是span/p给td添加类名
        e.target.parentElement.classList.add(className);
      }
    },
    // 清除目标元素的类名
    clearTargetClass(e) {
      if (e.target.localName === 'th') {
        e.target.classList.remove('dragLine');
      } else if (e.target.localName === 'span' || e.target.localName === 'p') {
        e.target.parentElement.classList.remove('dragLine');
      }
    },
    // 列开始拖动
    dragstart(index){
      this.dragIndex = index;
      // 在父元素上触发鼠标按下事件
      const mouseDownEvent = this.createMouseUpEvent();
      this.pageObj.parentElement.dispatchEvent(mouseDownEvent);
    },
    // 列拖动中
    dragover(e){
      e.preventDefault();
      this.updateTargetClass(e, 'dragLine');
    },
    // 离开列
    dragleave(e){
      this.clearTargetClass(e);
    },
    // 列拖动释放触发
    drop(e,index,list){
      if (this.dragIndex !== index) {
        const source = list[this.dragIndex];
        list.splice(this.dragIndex, 1);
        list.splice(index, 0, source);
        this.dragIndex = null; // 排序变化后恢复索引
      }
      // 清除目标元素的类名
      this.clearTargetClass(e);
      // 创建鼠标抬起事件
      const mouseDownEvent = this.createMouseUpEvent();
      // 在父元素上触发鼠标按下事件
      this.pageObj.parentElement.dispatchEvent(mouseDownEvent);
      // 模拟点击 zoomBox 和清除样式
      this.zoomBox.click();
      this.listStyle = null;
    },
    // 开始修改列宽
    startColumn(list, index, type) {
      this.dragging = true;
      this.startX = event.clientX;
      this.columnList = list;
      this.columnIndex = index;
      this.columnType = type;
      document.addEventListener('mousemove', this.dragColumn);
      document.addEventListener('mouseup', this.endColumn, true); // useCapture为true，可以确保取消监听不受其他事件影响
    },
    // 鼠标移动修改列宽
    dragColumn(e){
      if (this.dragging) {
        const dragOffset = e.clientX - this.startX; // 移动的距离
        this.changeTableWidth(this.columnList, this.columnIndex, dragOffset);
        this.startX = e.clientX;
      }
    },
    // 鼠标移动结束
    endColumn(e){
      // if(this.columnType=='tfood'){
      //   let mouseX = e.clientX
      //   const table = document.getElementById('table');
      //   const thElements = table.querySelectorAll('th');
      //     thElements.forEach((th, index) => {
      //     const rect = th.getBoundingClientRect();
      //     if (Math.abs(mouseX - rect.left) < 10) {
      //       let left = Math.floor(rect.left)
      //       mouseX = left - mouseX
      //       this.changeTableWidth(this.columnList,this.columnIndex,mouseX)
      //     }
      //   });
      // }
      this.dragging = false;
      // 移除事件监听
      document.removeEventListener('mousemove', this.dragColumn);
      document.removeEventListener('mouseup', this.endColumn, true); //useCapture为true，可以确保取消监听不受其他事件影响
    },
    // 修改表格元素宽
    changeTableWidth(columnList ,columnIndex, dragOffset){
      const draggedColumn = columnList[columnIndex]; // 当前元素
      const draggedColumnNewWidth = draggedColumn.width + dragOffset; // 当前元素修改的宽
      if (columnIndex == columnList.length - 1) { // 判断移动是是否是最后一个让上一个宽改变
        const preColumn = columnList[columnIndex - 1] // 上一个元素
        const preColumnNewWidth = preColumn.width - dragOffset; // 修改的宽度
        if (draggedColumnNewWidth >= 30 && preColumnNewWidth >= 30) {
          draggedColumn.width = draggedColumnNewWidth;
          preColumn.width = preColumnNewWidth;
        }
      } else { // 不是最后一个让下一个宽度改变
        const nextColumn = columnList[columnIndex+1]; // 下一个元素
        const nextColumnNewWidth = nextColumn.width - dragOffset; // 修改的宽度
        if (draggedColumnNewWidth >= 30 && nextColumnNewWidth >= 30) {
          draggedColumn.width = draggedColumnNewWidth;
          nextColumn.width = nextColumnNewWidth;
        }
      }
    },
    // 移动到表头表尾
    moveTable(iconName){
      if(!this.containerStyle.height) return // 如果高不存在说明选中的是表格
      const table = document.getElementById('table');
      const countTable = document.getElementById('countTable');
      let index = this.list.findIndex(item=> item.type == 'table'); // 通过tpye=table判断表格在数组中第几项
      let top = parseInt(this.list[index].containerStyle.top); // 表格距离上边的位置
      let containerHeight = parseInt(this.containerStyle.height); // 选中盒子的高
      let height = table.clientHeight + countTable.clientHeight; // 表格的高
      if(iconName === 'meterHeader') {
        this.$set(this.containerStyle, 'top', (top - containerHeight)+'px');
      }else if(iconName === 'meterend'){
        this.$set(this.containerStyle, 'top', (top + height)+'px');
      }
    },
    // 设置文字样式
    setFontStyle(iconName) {
      let listStyle = this.listStyle
      // 根据iconName的名字修改对应的属性
      if (iconName == "FontWidth") {
        listStyle.fontWeight = (listStyle.fontWeight === 'bolder') ? 'normal' : 'bolder';
      } else if (iconName == "italic") {
        listStyle.fontStyle = (listStyle.fontStyle === 'italic') ? 'normal' : 'italic';
      } else if (iconName == "line") {
        listStyle.textDecoration = (listStyle.textDecoration === 'underline') ? 'none' : 'underline';
      } else if (iconName == "justifyLeft") {
        listStyle.textAlign = 'left'
      } else if (iconName == "justifyCenter") {
        listStyle.textAlign = 'center'
      } else if (iconName == "justifyRight") {
        listStyle.textAlign = 'right'
      }
    },
    // 生成唯一的ID
    generateUniqueId() {
      return Date.now() + Math.floor(Math.random() * 1000); // 基于时间戳+随机数
    },
    // 设置公共样式
    getLineStyle(lineForm, style) {
      let lineStyle = {
        fontFamily: 'PingFang SC',
        fontWeight: 'normal',
        fontSize: "16px",
        textAlign: 'left',
        textDecoration: 'none',
        lineHeight: '2px',
        borderColor: 'black',
        ...style,
      };
      if (typeof lineForm.text !== 'number' || lineForm.text <= 0) {
        lineForm.text = 2; // 默认值
      }
      let borderStyle = { backgroundColor: 'transparent', border: 'none' };

      // 辅助函数：生成线条样式
      const generateLine = (borderWidth, dimensionStyle = {}, containerDimension = {}) => ({
        type: 'line',
        style: { ...lineStyle, borderWidth, borderStyle: lineForm.type, ...dimensionStyle },
        containerStyle: { ...this.containerInitStyle, ...borderStyle, ...containerDimension },
      });
      switch (lineForm.line) {
        case '横线':
          return generateLine(`${lineForm.text}px 0px 0px`, { width: '100%'}, { height: '3px' });
        case '竖线':
          return generateLine(`0px 0px 0px ${lineForm.text}px`, { height: '100%'}, { width: '3px' });
        case '方框':
          return generateLine(`${lineForm.text}px`, { height: '100%', width: '100%' });
        default:
          return null;
      }
    },
    // 点击添加线段向list追加内容
    addLine(lineForm) { 
      let id = this.generateUniqueId(); // 生成ID
      let lineInfo = this.getLineStyle(lineForm, {});
      if (lineInfo) this.list.push({ id, ...lineInfo });
    },
    // 点击添加文字向list追加内容
    addList(name) {
      let id = this.generateUniqueId(); // 生成ID
      this.list.push({
        type: 'input',
        id,
        name,
        style: { ...this.initStyle, lineHeight:'25px' },
        containerStyle:{ ...this.containerInitStyle }
      })
    },
    // 点击文字条码线段显示弹框
    showBlletBox(text) {
      let dom = document.getElementById(text) // 根据text判断获取哪个元素
      if (!dom) {
        console.warn(`Element with ID ${text} not found.`);
        return;
      }
      // 默认弹框信息
      let info = {
        top: dom.offsetTop - dom.clientHeight / 2,
        left: dom.offsetLeft + dom.clientWidth / 1.5,
      }
      // 根据text类型设置不同的信息
      if (text === 'text') {
        this.textInfo = { ...info, show: !this.textInfo.show, text: "文字" };
      } else if (text === 'code') {
        this.codeInfo = { ...info, show: !this.codeInfo.show, text: "条码" };
      } else if (text === 'line2') {
        this.lineInfo = { ...info, show: !this.lineInfo.show, text: "线段" };
      }
    },
    // 修改首页样式
    changePageData(obj){
      for(let key in obj) {
        // 判断输入的类型是否是数字或是否存在 不符合的话使用上一次的
        if(typeof obj[key] != 'number' || !obj[key]) obj[key] = parseInt(this.pageData[key]);
        this.pageData[key] = obj[key]+'mm';
      }
    },
    // 点击头部或页面关闭弹框
    changeInfo() {
      this.textInfo.show = false;
      this.codeInfo.show = false;
      this.lineInfo.show = false;
    },
    //按下删除键删除list中的内容
    delList(id){
      this.list = this.list.filter(item=> item.id != id); // 将list中筛选掉
      this.$refs.RightCard.changeIdCheck(id); // 将子组件的check修改
    },
    // 鼠标滚轮
    mouseWheel(e) {
      const img = document.getElementById("pageBox");
      this.imgWidth = img.offsetWidth || img.width || img.clientWidth;
      this.imgHeight = img.offsetHeight || img.height || img.clientHeight;
      if (e.deltaY > 0) {
        this.imgWidth = `${this.imgWidth - 10}px`;
        this.imgHeight = `${this.imgHeight - 10}px`;
      } else {
        this.imgWidth = `${this.imgWidth + 10}px`;
        this.imgHeight = `${this.imgHeight + 10}px`;
      }
    },
    // 点击元素
    clickBox(item, index) {
      // 需要调整尺寸的div
      this.zoomBox = document.getElementById("select" + item.id);
      // 需要修改list中的style
      this.listStyle = this.list.find(itm => itm.id == item.id).style || null;
      this.containerStyle = this.list.find(itm => itm.id == item.id).containerStyle || null;
      // 获取鼠标按下时的数据下标
      this.select = index;
      // 设置元素的层级，当前点击的层级在最大层级上+1
      let zindex = this.setIndex();
      // this.zoomBox.style.zIndex = zindex + 1;
      this.containerStyle && this.$set(this.containerStyle,'zIndex',zindex + 1) // 如果containerStyle存在就设置层级
      item.type=='table' && this.$set(this.containerStyle,'zIndex',0) // 如果是table层级就放到最低
      // 监听键盘按下回退或删除事件
      this.zoomKeyDown(item);
      // 鼠标按下事件
      this.zoomBox.onmousedown = this.zoomDown;
      // 页面监听移动事件
      this.pageObj.onmousemove = this.mouseMove;
      // 鼠标松开事件
      this.pageObj.parentElement.addEventListener('mouseup', this.zoomUp);
    },
    // 鼠标移入
    downBox(e, item, index){
      // 如果元素在拖动就不触发点击事件
      if(this.isMove) return;
      // 需要调整尺寸的div
      this.zoomBox = document.getElementById("select" + item.id);
      // 鼠标按下事件
      this.zoomBox.onmousedown = this.zoomDown;
      this.zoomBox.classList.add('moveClass');
      // 鼠标离开的时候将类名清除 将事件滞空
      this.zoomBox.onmouseleave = (e)=>{ 
        e.stopPropagation() 
        this.zoomBox.classList.remove('moveClass');
        this.zoomBox.onmouseleave = null;
        this.zoomBox.onmousedown = null;
      };
    },
    // 设置元素浮层
    setIndex(item, index) {
      // 获取最大层级的元素z-index
      let max = 0;
      for (let i = 0; i < this.list.length; i++) {
        let obj = document.getElementById("select" + this.list[i].id);
        if (obj.style.zIndex) {
          if (max < obj.style.zIndex) {
            max = parseInt(obj.style.zIndex);
          }
        }
      }
      return max;
    },
    // 键盘按下
    zoomKeyDown(item){
      document.onkeydown = (event)=>{
        let e = event || window.event || arguments.callee.caller.arguments[0];
        if(e.target.nodeName !== 'INPUT' && e.target.nodeName !== "TEXTAREA" && (e.keyCode == 46 || e.keyCode == 8)) {
            if (item.type=='table') {
              this.$message.error('表格不能删除');
              return
            }
            this.delList(item.id);
            document.onkeydown = null; //取消监听键盘按下回退或删除事件
            // 删除了将元素的监听事件清空
            this.select = "";
            this.moveType = "";
            this.zoomBox.onmousedown = null;
            this.zoomBox.onmouseup = null;
            this.pageObj.onmousemove = null;
            this.pageObj.onmouseup = null;
            this.listStyle = null;
          }
      }
    },
    // 鼠标按下
    zoomDown(e) {
      this.isMove = true;
      // 去除鼠标默认事件
      document.oncontextmenu = function (e) {
        e.preventDefault();
      };
      // 阻止冒泡
      e.stopPropagation();
      this.zoomBox.click();
      let oEvent = e || event;
      let d = this.getDirection(oEvent);
      this.zoomBox.onmouseup = this.boxUp;
      // 当位置为四个边和四个角时才开启尺寸修改
      if (d === "move" || d === "") {
        this.disX = oEvent.clientX - this.zoomBox.offsetLeft;
        this.disY = oEvent.clientY - this.zoomBox.offsetTop;
        this.moveType = "drag";
      } else {
        this.moveType = "resizeable";
        this.direc = d;
        this.clientX = e.clientX;
        this.clientY = e.clientY;
      }
    },
    // 鼠标移动
    mouseMove(e) {
      let that = this;
      let oEvent = e || event;
      let d = this.getDirection(oEvent);
      let cursor = "";
      if (d === "move" || d === "") {
        // 默认移动鼠标样式
        cursor = "move";
      } else {
        // 缩放鼠标样式
        cursor = d + "-resize";
      }
      // 当鼠标抬起时，this.moveType这个字段清空，并后面内容将不执行
      if (this.moveType == "") return;

      let box = document.getElementsByClassName("container");
      // 剔除当前下标的元素，获取其他元素数组
      let otherBox = Array.from(box).filter(
        (item, index) => index != that.select
      );
      //! 获取当前元素
      let currentBox = null;
      currentBox = Array.from(box)[this.select];
      let {
        currentBoxHeight,
        currentBoxTop,
        currentBoxMeddle,
        currentBoxBottom,
        currentBoxWidth,
        currentBoxLeft,
        currentBoxMeddle2,
        currentBoxRight,
      } = that.packageInfo(currentBox, null);

      //! 获取与当前元素对比的对比元素
      let contrastBox = {};
      /**
       * 获取到其他元素数组后，进行循环遍历。判断条件有两种情况
       *  !情况1： 当两者元素的高度一致时，出现3条辅助线
       *  !情况2： 当两者元素的高度不一致时，出现1条辅助线
       */
      otherBox.forEach((item) => {
        let {
          contrastBoxHeight,
          contrastBoxTop,
          contrastBoxMeddle,
          contrastBoxBottom,
          contrastBoxWidth,
          contrastBoxLeft,
          contrastBoxMeddle2,
          contrastBoxRight,
        } = that.packageInfo(null, item);
        if (!contrastBoxTop) return;

        // 根据元素的上边距值相减,绝对值最小的两个div最近,那么就展示辅助线
        if (contrastBoxHeight == currentBoxHeight) {
          if (Math.abs(currentBoxBottom - contrastBoxBottom) > 5) {
            this.clearLine();
          } else {
            contrastBox = item;
          }
        } else {
          if (Math.abs(currentBoxTop - contrastBoxTop) > 5) {
            this.$refs.lineTopX.style.width = "0";
          } else {
            contrastBox = item;
          }
          if (Math.abs(currentBoxMeddle - contrastBoxMeddle) > 5) {
            this.$refs.lineMeddleX.style.width = "0";
          } else {
            contrastBox = item;
          }
          if (Math.abs(currentBoxBottom - contrastBoxBottom) > 5) {
            this.$refs.lineBottomX.style.width = "0";
          } else {
            contrastBox = item;
          }
        }
        // 根据元素的左边距值相减,绝对值最小的两个div最近,那么就展示辅助线
        if (currentBoxWidth == contrastBoxWidth) {
          if (Math.abs(currentBoxLeft - contrastBoxLeft) > 5) {
            this.clearLine();
          } else {
            contrastBox = item;
          }
        } else {
          if (Math.abs(currentBoxLeft - contrastBoxLeft) > 5) {
            this.$refs.lineTopY.style.height = "0";
          } else {
            contrastBox = item;
          }
          if (Math.abs(currentBoxMeddle2 - contrastBoxMeddle2) > 5) {
            this.$refs.lineMeddleY.style.height = "0";
          } else {
            contrastBox = item;
          }
          if (Math.abs(currentBoxRight - contrastBoxRight) > 5) {
            this.$refs.lineBottomY.style.height = "0";
          } else {
            contrastBox = item;
          }
        }
      });
      // 
      if (Object.getOwnPropertyNames(contrastBox).length != 0) {
        that.contrastBoxs = contrastBox;
        that.guideLine = null;
        // 判断两个元素的上边距，是否在区间内，是的话就展示辅助线，否则则不展示
        let compareTop = compareTopHeight(contrastBox, currentBox, 5, "1");
        // 判断两个元素的左边框，是否在区间内，是的话就展示辅助线，否则则不展示
        let compareLeft = compareTopHeight(contrastBox, currentBox, 5, "4");
        // 判断两个元素的中心点，是否在区间内，是的话就展示辅助线，否则则不展示
        let compareMeddle = compareTopHeight(contrastBox, currentBox, 5, "2");
        // 判断两个元素的中心点，是否在区间内，是的话就展示辅助线，否则则不展示
        let compareMeddle2 = compareTopHeight(contrastBox, currentBox, 5, "5");
        // 判断两个元素的下边框，是否在区间内，是的话就展示辅助线，否则则不展示
        let compareBottom = compareTopHeight(contrastBox, currentBox, 5, "3");
        // 判断两个元素的左边框，是否在区间内，是的话就展示辅助线，否则则不展示
        let compareRight = compareTopHeight(contrastBox, currentBox, 5, "6");

        // 当为1时则展示上边框辅助线
        if (compareTop) {
          this.getDomInfo(currentBox, contrastBox, "1");
          this.guideLine = "1";
        } else {
          this.$refs.lineTopX.style.width = "0";
        }
        // 当为3时则展示中间辅助线
        if (compareMeddle) {
          this.getDomInfo(currentBox, contrastBox, "3");
          that.guideLine = "3";
        } else {
          this.$refs.lineMeddleX.style.width = "0";
        }
        // 当为4时则展示下边框辅助线
        if (compareBottom) {
          this.getDomInfo(currentBox, contrastBox, "4");
          that.guideLine = "4";
        } else {
          this.$refs.lineBottomX.style.width = "0";
        }
        // 当为5时则展示左边框辅助线
        if (compareLeft) {
          this.getDomInfo(currentBox, contrastBox, "5");
          this.guideLine = "5";
        } else {
          this.$refs.lineTopY.style.height = "0";
        }
        // 当为7时则展示中间辅助线
        if (compareMeddle2) {
          this.getDomInfo(currentBox, contrastBox, "7");
          that.guideLine = "7";
        } else {
          this.$refs.lineMeddleY.style.height = "0";
        }
        // 当为8时则展示右边框辅助线
        if (compareRight) {
          this.getDomInfo(currentBox, contrastBox, "8");
          that.guideLine = "8";
        } else {
          this.$refs.lineBottomY.style.height = "0";
        }
      } else {
        that.contrastBoxs = null;
      }
      // 修改鼠标显示效果
      this.zoomBox.style.cursor = cursor;
      if (this.moveType === "resizeable") {
        // 缩放
        this.zoomBox.style.cursor = this.direc + "-resize";
        this.zoomMove(oEvent);
      } else if (this.moveType === "drag") {
        this.zoomBox.style.cursor = "move";
        this.eleMousemove(oEvent);
      }
    },
    // 缩放移动
    zoomMove(e) {
      // 当开启尺寸修改时，鼠标移动会修改div尺寸
      if (this.moveType === "resizeable") {
        // 鼠标按下的位置在右边，修改宽度
        if (this.direc.indexOf("e") !== -1) {
          // this.zoomBox.style.width
          const newWidth = Math.min(
            Math.max(this.minW,this.zoomBox.offsetWidth + (e.clientX - this.clientX)),
            this.pageObj.offsetWidth - this.zoomBox.offsetLeft
          )
          this.containerStyle.width = newWidth+'px';
          this.clientX = e.clientX;
        }
        // 鼠标按下的位置在上部，修改高度
        if (this.direc.indexOf("n") !== -1) {
          // this.zoomBox.style.height
          const newHeight = Math.min(
            Math.max(this.minH,this.zoomBox.offsetHeight + (this.clientY - e.clientY)),
            this.pageObj.offsetHeight - this.zoomBox.offsetTop
          )
          this.containerStyle.height = newHeight+"px";
          this.containerStyle.top = parseInt(this.containerStyle.top)-(this.clientY - e.clientY)+'px'
          this.clientY = e.clientY;
        }
        // 鼠标按下的位置在底部，修改高度
        if (this.direc.indexOf("s") !== -1) {
          // this.zoomBox.style.height
          const newHeight = Math.min(
            Math.max(this.minH,this.zoomBox.offsetHeight + (e.clientY - this.clientY)),
            this.pageObj.offsetHeight - this.zoomBox.offsetTop
          )
          this.containerStyle.height = newHeight+"px";
          this.clientY = e.clientY;
        }
        // 鼠标按下的位置在左边，修改宽度
        if (this.direc.indexOf("w") !== -1) {
          // this.zoomBox.style.width
          const newWidth = Math.min(
            Math.max(this.minW,this.zoomBox.offsetWidth + (this.clientX - e.clientX)),
            this.pageObj.offsetWidth - this.zoomBox.offsetLeft
          )
          this.containerStyle.width = newWidth+'px';
          this.containerStyle.left = parseInt(this.containerStyle.left)-(this.clientX - e.clientX)+'px'
          this.clientX = e.clientX;
        }
      }
    },
    // 鼠标拖拽移动
    eleMousemove(oEvent) {
      // 加入该判断拖拽更流畅
      if (this.moveType === "drag") {
        // 计算点击元素到父级元素的定位top，left距离
        let l = oEvent.clientX - this.disX;
        let t = oEvent.clientY - this.disY;
        /** 限定拖拽范围，限定拖拽元素在指定的范围内 */
        // 限定左边界和上边界
        if (l < 0) {
          l = 0;
        }
        if (t < 0) {
          t = 0;
        }
        // 限定右边界的距离(当l=父元素宽-子元素宽时，刚好子元素放在父元素最右边)
        if (l > this.pageObj.clientWidth - this.zoomBox.clientWidth) {
          l = this.pageObj.clientWidth - this.zoomBox.clientWidth;
        }
        // 限定下边界的距离(当t=父元素高-子元素高时，刚好子元素放在父元素最下边)
        if (t > this.pageObj.clientHeight - this.zoomBox.clientHeight) {
          t = this.pageObj.clientHeight - this.zoomBox.clientHeight;
        }
        this.zoomBox.style.left = l + "px";
        this.zoomBox.style.top = t + "px";
        this.containerStyle.left = l + "px";
        this.containerStyle.top = t + "px";
      }
    },
    // 操作元素的鼠标抬起事件
    boxUp(e) {
      let that = this;
      // 阻止冒泡
      e.stopPropagation();
      let oEvent = e || event;
      // 获取当前操作的元素
      let currentBox = oEvent.target.parentElement;
      // 获取当前元素和对比元素的个别参数
      let {
        currentBoxHeight,
        contrastBoxTop,
        contrastBoxMeddle,
        contrastBoxBottom,
        currentBoxWidth,
        contrastBoxLeft,
        contrastBoxMeddle2,
        contrastBoxRight,
      } = that.packageInfo(currentBox, that.contrastBoxs);
      // 当前选择对象鼠标抬起事件
      this.isMove = false;
      this.zoomBox.style.cursor = '';
      this.moveType = "";
      this.zoomBox.onmouseup = null;
      this.zoomBox.onmousedown = null;
      this.clearLine();
      if (
        Object.prototype.toString.call(that.contrastBoxs) != "[object Null]"
      ) {
        let arr = ['td','p','span']
        if(currentBox==this.pageObj || arr.includes(oEvent.target.localName)) return
        if (this.guideLine == "1" && contrastBoxTop>0) {
          currentBox.style.top = contrastBoxTop + "px";
          this.containerStyle.top = currentBox.style.top;
        } else if (this.guideLine == "3") {
          let result = Number(contrastBoxMeddle) - Number(currentBoxHeight) / 2;
          if(result<0) return
          currentBox.style.top = result + "px";
          this.containerStyle.top = currentBox.style.top;
        } else if (this.guideLine == "4") {
          let result = Number(contrastBoxBottom) - Number(currentBoxHeight);
          if(result<0) return
          currentBox.style.top = result + "px";
          this.containerStyle.top = currentBox.style.top
        } else if (this.guideLine == "5" && contrastBoxLeft>0) {
          currentBox.style.left = contrastBoxLeft + "px";
          this.containerStyle.left = currentBox.style.left;
        } else if (this.guideLine == "7") {
          let result = Number(contrastBoxMeddle2) - Number(currentBoxWidth) / 2;
          if(result<0) return
          currentBox.style.left = result + "px";
          this.containerStyle.left = currentBox.style.left;
        } else if (this.guideLine == "8") {
          let result = Number(contrastBoxRight) - Number(currentBoxWidth);
          if(result<0) return
          currentBox.style.left = result + "px";
          this.containerStyle.left = currentBox.style.left;
        }
      }
      
      this.pageObj.onmousemove = null;
      this.pageObj.onmouseup = null;
      this.contrastBoxs = null
    },
    // 操作元素的父级元素鼠标抬起事件
    zoomUp(e) {
      // 阻止冒泡
      e.stopPropagation();
      // 点击当前选择的任意位置鼠标抬起事件，选择状态清空
      this.moveType = "";
      this.zoomBox.onmousedown = null;
      this.zoomBox.onmouseup = null;
      this.pageObj.onmousemove = null;
      this.pageObj.onmouseup = null;
      this.containerStyle = null;
      this.contrastBoxs = null;
      document.onkeydown = null;
      this.isMove = false;
      this.clearLine();
      this.pageObj.parentElement.removeEventListener('mouseup',this.zoomUp);
    },
    // 获取鼠标所在div的位置
    getDirection(ev) {
      let dir = "";
      if (ev.target.className.indexOf("top") >= 0) {
        dir += "n";
      } else if (ev.target.className.indexOf("bottom") >= 0) {
        dir += "s";
      }
      if (ev.target.className.indexOf("left") >= 0) {
        dir += "w";
      } else if (ev.target.className.indexOf("right") >= 0) {
        dir += "e";
      }
      if (ev.target.className === "") {
        dir = "move";
      }
      return dir;
    },

    /**
     * !获取关键元素
     * param1: 当前选中的元素
     * param2: 对比选中的元素
     * param3: 用来区分两者元素高度是否一致
     *  当为1时,代表两者高度一致,则出现3条横向辅助线
     *  当为2时,出现上边框横向辅助线
     *  当为3时,出现中心横向辅助线
     *  当为4时,出现下边框横向辅助线
     *  当为5时,出现左边框竖向辅助线
     */
    getDomInfo(currentEvent, contrastEvent, key) {
      let that = this;
      // 获取当前点击的元素信息
      let currentDom = currentEvent;
      let currentLeft = replaceFun(currentDom.style.left);
      let currentTop = replaceFun(currentDom.style.top);
      let currentHeight = replaceFun(currentDom.style.height);
      let currentWidth = replaceFun(currentDom.style.width);
      // 获取对比元素信息
      let contrastDom = contrastEvent;
      let contrastLeft = replaceFun(contrastDom.style.left);
      let contrastTop = replaceFun(contrastDom.style.top);
      let contrastHeight = replaceFun(contrastDom.style.height);
      let contrastWidth = replaceFun(contrastDom.style.width);

      /**
       * ! 横线的宽度计算
       * 当对比元素在选中元素右侧时，宽度 = 对比元素的左边距 - 选中元素的左边距 + 对比元素的宽度
       * 当对比元素在选中元素左侧时，宽度 = 选中元素的左边距 - 对比元素的左边距 + 选中元素的宽度
       * ! 竖线的高度计算
       * 当对比元素在选中元素上方时，高度 = 选中元素的上边距 - 对比元素的上边距 + 选中元素的高度
       * 当对比元素在选中元素下方时，高度 = 对比元素的上边距 - 对比元素的下边距 + 对比元素的高度
       */
      let resultWidthX =
        contrastLeft > currentLeft ? contrastWidth : currentWidth;
      let width = Math.abs(contrastLeft - currentLeft);

      let resultHeightY =
        contrastTop > currentTop ? contrastHeight : currentHeight;
      let height = Math.abs(currentTop - contrastTop);
      /**
       * ! 当key为1时，出现上边框横向辅助线
       *  计算lineTopX宽度 = width + 对比元素/选中元素的宽度
       *  计算lineTopX的左边距 = 对比元素在选中元素左侧时，使用对比元素的左边距；反之使用选中元素的左边距
       *  计算lineTopX的上边距 = 对比元素的上边距 - 1
       *
       * ! 当key为3时，出现中间横向辅助线
       *  计算lineMeddleX的宽度 = width + 对比元素/选中元素的宽度
       *  计算lineMeddleX的左边距 = 对比元素在选中元素左侧时，使用对比元素的左边距；反之使用选中元素的左边距
       *  计算lineMeddleX的上边距 = 对比元素的上边距 + 选中元素的高度 / 2 - 1
       *
       * ! 当key为4时，出现下边框横向辅助线
       *  计算lineMeddleX的宽度 = width + 对比元素/选中元素的宽度
       *  计算lineMeddleX的左边距 = 对比元素在选中元素左侧时，使用对比元素的左边距；反之使用选中元素的左边距
       *  计算lineMeddleX的上边距 = 对比元素的上边距 + 选中元素的高度 / 2 - 1
       *
       * ! 当key为5时，出现左边框竖向辅助线
       *  计算lineTopY的高度 = height + 对比元素/选中元素的高度
       *  计算lineTopY的左边距 = 对比元素的左边距 - 1
       *  计算lineTopY的上边距 = 对比元素/选中元素的上边距
       *
       * ! 当key为7时，出现中间竖向辅助线
       *  计算lineTopY的高度 = height + 对比元素/选中元素的高度
       *  计算lineTopY的左边距 = 对比元素的左边距 + 对比元素的宽度 / 2 - 1
       *  计算lineTopY的上边距 = 对比元素/选中元素的上边距
       * ! 当key为8时，出现右边框竖向辅助线
       *  计算lineTopY的高度 = height + 对比元素/选中元素的高度
       *  计算lineTopY的左边距 = 对比元素的左边距 + 对比元素的宽度 - 1
       *  计算lineTopY的上边距 = 对比元素/选中元素的上边距
       */
      if (key == 1 || key == 3 || key == 4) {
        this.XtransverseList.forEach((item, index) => {
          that.$refs[item].style.left =
            currentLeft > contrastLeft
              ? contrastLeft + "px"
              : currentLeft + "px";
          that.$refs[item].style.top =
            contrastTop - 1 + (contrastHeight * index) / 2 + "px";
        });
      } else if (key == 5 || key == 7 || key == 8) {
        this.YtransverseList.forEach((item, index) => {
          that.$refs[item].style.left =
            contrastLeft + (contrastWidth / 2) * index - 1 + "px";
          that.$refs[item].style.top =
            currentTop > contrastTop ? contrastTop + "px" : currentTop + "px";
        });
      }
      if (key == 1) {
        that.$refs.lineTopX.style.width = width + resultWidthX + "px";
      } else if (key == 3) {
        that.$refs.lineMeddleX.style.width = width + resultWidthX + "px";
      } else if (key == 4) {
        that.$refs.lineBottomX.style.width = width + resultWidthX + "px";
      } else if (key == 5) {
        that.$refs.lineTopY.style.height = height + resultHeightY + "px";
      } else if (key == 7) {
        that.$refs.lineMeddleY.style.height = height + resultHeightY + "px";
      } else if (key == 8) {
        that.$refs.lineBottomY.style.height = height + resultHeightY + "px";
      }
    },

    // 将辅助线清空
    clearLine() {
      this.XtransverseList.forEach((item) => {
        this.$refs[item].style.width = "0";
      });
      this.YtransverseList.forEach((item) => {
        this.$refs[item].style.height = "0";
      });
    },

    /**
     * ! 封装的函数，用于获取当前元素和对比元素的个别参数信息
     * param1: 当前元素
     * param2: 对比元素
     */
    packageInfo(currentBox = null, contrastBox = null) {
      let currentBoxHeight,
        currentBoxTop,
        currentBoxMeddle,
        currentBoxBottom,
        currentBoxWidth,
        currentBoxLeft,
        currentBoxMeddle2,
        currentBoxRight;
      if (Object.prototype.toString.call(currentBox) != "[object Null]") {
        //! 获取当前元素的高度
        currentBoxHeight = replaceFun(currentBox.style.height);
        //! 获取当前元素的上边距
        currentBoxTop = replaceFun(currentBox.style.top);
        //! 获取当前元素的中心距离
        currentBoxMeddle =
          replaceFun(currentBox.style.top) + currentBoxHeight / 2;
        //! 获取当前元素的下边距
        currentBoxBottom = replaceFun(currentBox.style.top) + currentBoxHeight;
        //! 获取当前元素的宽度
        currentBoxWidth = replaceFun(currentBox.style.width);
        //! 获取当前元素的左边距
        currentBoxLeft = replaceFun(currentBox.style.left);
        //! 获取当前元素的中心距离
        currentBoxMeddle2 =
          replaceFun(currentBox.style.left) + currentBoxWidth / 2;
        //! 获取当前元素的右边距
        currentBoxRight = replaceFun(currentBox.style.left) + currentBoxWidth;
      }
      let contrastBoxHeight,
        contrastBoxTop,
        contrastBoxMeddle,
        contrastBoxBottom,
        contrastBoxWidth,
        contrastBoxLeft,
        contrastBoxMeddle2,
        contrastBoxRight;
      if (Object.prototype.toString.call(contrastBox) != "[object Null]") {
        //! 对比元素的高度
        contrastBoxHeight = replaceFun(contrastBox.style.height);
        //! 对比元素的上边距
        contrastBoxTop = replaceFun(contrastBox.style.top);
        //! 对比元素的中心距离
        contrastBoxMeddle =
          replaceFun(contrastBox.style.top) + contrastBoxHeight / 2;
        //! 对比元素的下边距
        contrastBoxBottom =
          replaceFun(contrastBox.style.top) + contrastBoxHeight;
        //! 对比元素的宽度
        contrastBoxWidth = replaceFun(contrastBox.style.width);
        //! 对比元素的左边距
        contrastBoxLeft = replaceFun(contrastBox.style.left);
        //! 对比元素的中心距离
        contrastBoxMeddle2 =
          replaceFun(contrastBox.style.left) + contrastBoxWidth / 2;
        //! 对比元素的右边距
        contrastBoxRight =
          replaceFun(contrastBox.style.left) + contrastBoxWidth;
      }

      return {
        currentBoxHeight,
        currentBoxTop,
        currentBoxMeddle,
        currentBoxBottom,
        currentBoxWidth,
        currentBoxLeft,
        currentBoxMeddle2,
        currentBoxRight,

        contrastBoxHeight,
        contrastBoxTop,
        contrastBoxMeddle,
        contrastBoxBottom,
        contrastBoxWidth,
        contrastBoxLeft,
        contrastBoxMeddle2,
        contrastBoxRight,
      };
    },
    // 当勾选右侧内容时,通过自定义事件向list追加内容
    operate(data) {
      // 公共计算left和top
      const calculatePosition = (num, topOffset = 0) => {
        let pageWidth = this.pageObj.offsetWidth;
        let left = Math.max(130 * num - Math.floor((130 * num + 130) / pageWidth) * pageWidth, 0) + 'px';
        let top = Math.floor((130 * num + 130) / pageWidth) * 60 + topOffset + 'px';
        return { left, top };
      };
      // 公共的添加或删除操作
      const modifyList = (data, left, top) => {
        let query = {
          name: data.name,
          type: data.type,
          id: data.id,
          style: { ...this.initStyle },
          containerStyle: { ...this.containerInitStyle, left, top },
          check: data.check,
          index: data.index,
          isCustom: data.isCustom,
        };
        if (data.check) {
          this.list.push(query);
        } else {
          let index = this.list.findIndex((item) => item.id == data.id);
          if (index !== -1) this.list.splice(index, 1);
        }
      };
      // 公共处理表格列或底部行的添加或删除
      const addOrRemoveItem = (check, listKey, dataItem, tableList, isTable) => {
        //! 当check为true时,表示追加至list数组内
        if (check) {
          if (tableList) {
            tableList[listKey].push(dataItem); // 添加到现有表格
          } else {
            const containerStyle = {
              width: this.pageObj.offsetWidth + 'px',
              top: isTable ? '100px' : '240px',
              height: "240px",
              maxHeight: '300px',
            };
            const newQuery = {
              id: 99999,
              type: 'table',
              containerStyle,
              check: data.check,
              style: { ...this.initStyle, lineHeight: '25px', textAlign: 'center' },
              columns: isTable ? [{ ...dataItem, width:this.pageObj.offsetWidth+'px' }] : [],
              countList: isTable ? [] : [{ ...dataItem, width:this.pageObj.offsetWidth+'px' }]
            };
            this.list.push(newQuery); // 创建新表格
          }
          //! 反之则从list中的tableList剔除对应的标签
        } else {
          const itemIndex = tableList[listKey].findIndex(item => item.id === dataItem.id);
          if (itemIndex !== -1) tableList[listKey].splice(itemIndex, 1); // 删除对应项
        }
      };
      // 公共更新表格列宽
      const updateTableColumnWidths = (tableList, isTable) => {
        if (tableList) {
          const width = this.pageObj.offsetWidth;
          const key = isTable ? 'columns' : 'countList';
          const tableWidth = Math.floor(width / tableList[key].length);
          tableList[key].forEach(item => {
            this.$set(item, 'width', tableWidth);
          });
        }
      };
      // 处理不同类型的操作
      if (data.type == "inputCheck") {
        // 处理订单信息的操作
        let { left, top } = calculatePosition(data.index - 1, 20);
        modifyList(data, left, top);
      } else if(data.type == "sign"){
        // 处理签字操作
        let { left, top } = calculatePosition(data.index - 1, data.top);
        modifyList(data, left, top);
      } else if(data.type == "table" || data.type == "table-tfoot") {
        // 处理表格类型的操作
        const isTable = data.type === "table"; // 判断是表格还是表格底部
        let tableList = this.list.find(item => item.type === 'table');
        const itemData = { name: data.name, id: data.id, index: data.index };
        // 添加或删除表格列/底部行
        addOrRemoveItem(data.check, isTable ? 'columns' : 'countList', itemData, tableList, isTable);
        // 更新表格列宽
        updateTableColumnWidths(tableList, isTable);
      } else if (data.type == "change") {
        // 处理修改输入框标签的操作
        let index = this.list.findIndex((item) => item.id === data.id);
        if(index === -1){
          let tableIndex = this.list.findIndex(item=>item.type === 'table');
          let obj = this.list[tableIndex].columns.find(item => item.id === data.id);
          if (!obj) obj = this.list[tableIndex].countList.find(item=>item.id === data.id);
          obj.name = data.newName || data.name;
        }else{
          this.list[index].name = data.newName || data.name;
        }
      }
    },
    // 清空选中效果和样式 
    clearStyle() {
      this.select = '';
      this.listStyle = null;
    },
    // 表单数据处理
    handleFontSizeChange(e) {
      const type = this.getFontAttributeType();
      this.listStyle[type] = `${e}px`;
    },
    handleFontAttributeValueChange(val) {
      const type = this.getFontAttributeType();
      this.form.fontSize = this.listStyle[type] ? parseInt(this.listStyle[type]) : val != 1 ? 16 : 1;
    },
    handleFontFamilyChange(val) {
      let fontInfo = fontFamily.find(item=> item.id == val);
      if(fontInfo) this.listStyle.fontFamily = fontInfo.font;
    },
    handleConfigurationChange(val) {
      document.getElementById("pageBox").style.transform = `scale(${parseInt(val) / 100})` // 设置页面展示百分比
    },
    // 获取当前字体属性的type
    getFontAttributeType() {
      return this.fontAttribute[this.form.fontAttributeValue - 1].type;
    },
  },
};
</script>

<style lang="scss" scoped>
$dominantColor: #07a453;

#pageBox {
  width: var(--width);
  height: var(--height);
  padding-top: var(--top);
  padding-left: var(--left);
  border: 1px solid #9c9c9c;
  position: relative;
  color: #fff;
  background-color: #fff;
  background-image: conic-gradient(at calc(100% - 2px) calc(100% - 2px),
      #d5d8dc 270deg,
      #fafafad5 0),
    conic-gradient(at calc(100% - 1px) calc(100% - 1px),
      #a9a9a9 270deg,
      #e4e4e4d5 0);
  background-size: 100px 100px, 20px 20px;
  margin: 50px auto 50px;

  .pageBox-line {
    position: absolute;
    left: 0;
    top: -14px;
    height: 1px;
    width: 100%;
    background-color: $dominantColor;

    &::before {
      content: "";
      display: block;
      position: absolute;
      top: -5px;
      left: 0;
      height: 11px;
      width: 1px;
      background-color: $dominantColor;
    }

    &::after {
      content: "";
      display: block;
      position: absolute;
      top: -5px;
      right: 0;
      height: 11px;
      width: 1px;
      background-color: $dominantColor;
    }

    .title {
      position: absolute;
      width: auto;
      height: 14px;
      line-height: 14px;
      font-size: 12px;
      border: 1px solid $dominantColor;
      border-radius: 2px;
      color: $dominantColor;
      background-color: #fff;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
  }

  .pageBox-vertical {
    position: absolute;
    top: 0;
    right: -14px;
    width: 1px;
    height: 100%;
    background-color: $dominantColor;

    &::before {
      content: "";
      display: block;
      position: absolute;
      right: -5px;
      top: 0;
      width: 11px;
      height: 1px;
      background-color: $dominantColor;
    }

    &::after {
      content: "";
      display: block;
      position: absolute;
      right: -5px;
      bottom: 0;
      width: 11px;
      height: 1px;
      background-color: $dominantColor;
    }

    .title {
      position: absolute;
      width: 14px;
      height: auto;
      line-height: 1;
      font-size: 12px;
      border: 1px solid $dominantColor;
      border-radius: 2px;
      color: $dominantColor;
      background-color: #fff;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      -ms-writing-mode: tb-lr;
      writing-mode: vertical-lr;
    }
  }
}

.content {
  width: 100%;
  height: 100%;

  &-top {
    width: 100%;
    height: 66px;
    box-shadow: 0 2px 3px #e1e1e1;
    background: #fff;
    align-items: center;
    padding: 0 20px;
    position: relative;
    z-index: 99;

    &-left {
      align-items: center;
      gap: 10px;
    }
  }

  &-left {
    width: 66px;
    height: calc(100% - 66px);
    background: #fafafc;

    &-box {
      width: 66px;
      height: 66px;
      align-items: center;
      font-size: 12px;
      font-weight: 500;

      &:hover {
        color: #03a98e;
        cursor: pointer;
      }
    }
  }

  &-right {
    width: 340px;
    height: calc(100% - 66px);
    background: #fafafc;
    position: absolute;
    right: 0;
    top: 66px;
  }

  &-meddle {
    width: calc(100% - 66px - 340px);
    height: calc(100% - 66px);
    background: #eeeeee;
    position: absolute;
    left: 66px;
    top: 66px;
    overflow-y: auto;
    .container {
      box-sizing: border-box;
      position: absolute;
      cursor: default;
      border: 1px solid #dadada;
      background: #fff;
      color: #333333;
      user-select: none;
    }

    .point {
      width: 10px;
      height: 10px;
      border-radius: 2px;
      border: 1px solid $dominantColor;
      position: absolute;
    }

    .top {
      top: -5px;
      left: 50%;
    }

    .bottom {
      bottom: -5px;
      left: 50%;
    }

    .left {
      left: -5px;
      top: calc((100% - 10px) / 2);
    }

    .right {
      right: -5px;
      top: calc((100% - 10px) / 2);
    }

    .top-left {
      top: -5px;
      left: -5px;
    }

    .bottom-left {
      bottom: -5px;
      left: -5px;
    }

    .top-right {
      top: -5px;
      right: -5px;
    }

    .bottom-right {
      bottom: -5px;
      right: -5px;
    }

    .Xline {
      position: absolute;
      height: 1px;
      border-bottom: 1px dashed #cf0a0a;
      z-index: 99;
    }

    .Yline {
      position: absolute;
      width: 1px;
      border-left: 1px dashed #cf0a0a;
      z-index: 99;
    }
  }
}

.selectFontSize {
  width: 88px;
}

.iconCard {
  border: 1px solid #e1e1e1;
  padding: 5px;
  display: flex;
  gap: 5px;
}

.width100 {
  width: 100px;
}

.width170 {
  width: 170px;
}

textarea {
  resize: vertical;
  overflow: auto;
}

.container div img{
  width: 100%;
  height: 100%;
}

table{
  width: 100%;
  border-collapse: collapse;
}

td,
th{
  border: 1px solid #000;
  border-collapse: collapse;
  padding: 2px 4px;
  position: relative;
}

table .resizable{
  position: absolute;
  right: -5px;
  top: 0;
  width: 10px;
  height: 100%;
  cursor: col-resize;
  opacity: .6;
  z-index: 999;
}
th{
  text-align: inherit;
  font-weight: inherit;

}

table th.dragLine{
  border-left: 2px dashed $dominantColor;
}
.moveClass{
   cursor: move !important;
   border: 1px solid $dominantColor !important;
}

.user-select-none {
  -webkit-user-select: none; /* Chrome/Safari */
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* Internet Explorer/Edge */
  user-select: none; /* Non-prefixed version, currently supported by most modern browsers */
}
.top, .top-right, .top-left {
  cursor: n-resize;
}

.left, .right {
  cursor: ew-resize;
}

.bottom, .bottom-left, .bottom-right {
  cursor: s-resize;
}

.top-right, .bottom-left {
  cursor: ne-resize;
}

.top-left, .bottom-right {
  cursor: nw-resize;
}
.qrcode{
  width: 80px;
  height: 80px;
  background-image: url("https://copartner.oss-cn-beijing.aliyuncs.com/logo/2405/11/i3YxmrZZHXQIsjTyip3kwVyFmhdxboZ3cCq899vk.png");
  background-position: center;
  background-size: 80px 80px;
  background-repeat: no-repeat;
}
</style>